package gitobject;

import Utils.addUtils;
import Utils.commitUtils;
import Utils.tempWorkTree;
import core.JitCommit;
import fileoperation.FileCreation;
import repository.Repository;
import sha1.SHA1;

import zlib.ZLibUtils;
import fileoperation.FileReader;

import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

//Tree继承自GitObject, 可序列化
public class Tree extends GitObject implements Serializable {
    private String value;

    public Tree() {
    }

    /**
     * Constructor
     *
     * @param file
     * @throws Exception
     */
    public Tree(File file) throws Exception {
        this.fmt = "tree";
        this.mode = "040000";
        this.value = "";
        key = genKey(file);
        compressWrite();
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    /**
     * Deserialize a tree object with treeId and its path.
     * @param Id
     * @param Id
     * @throws IOException
     */
    public static Tree deserialize(String Id) throws IOException {
        try {
            //1.在路径中寻找该文件2.找到之后读取该文件3.将其返回,没找到的话返回null
            File dir = new File(tempWorkTree.gitDir + File.separator + "objects");
            File[] fs = dir.listFiles();//Objects下的文件列表
            for (int i = 0; i < fs.length; i++) {
                if (fs[i].isFile() && fs[i].getName().equals(Id)) {
                    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(fs[i]));
                    Tree tree = (Tree) objectInputStream.readObject();
                    return tree;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    /**
     * Sort the files in a certain order. You should consider whether it's a file or a directory.
     *
     * @param fs
     * @return List
     */
    public static List sortFile(File[] fs) {
        List fileList = Arrays.asList(fs);
        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isFile() && o2.isDirectory())
                    return 1;
                return o1.compareTo(o2);
            }
        });
        return fileList;
    }

    /**
     * Generate the key of a tree object.
     *
     * @param dir
     * @return String
     * @throws Exception
     */
    public String genKey(File dir) throws Exception {
        String treeKey = DirSHA1(dir);
        return treeKey;
    }

    static String result = "";

    public static String DirSHA1(File file) throws IOException {
        result = "";
        String filePath = file.getPath();//文件目录
        try {
            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
            dfs(filePath);
            if (result.equals("")) {
                //System.out.println(md5.digest(filePath.getBytes()));
                //System.out.println("文件夹为空");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    public static void dfs(String path) throws Exception {//文件DFS
        
        String index=addUtils.readAllIndex(tempWorkTree.indexLoc);
        File dir = new File(path);
        File[] fs = dir.listFiles();
        List fileList = sortFile(fs);
        String s = Commit.getLastCommit();
        if (fs == null)
            return;
        for (Object obj : fileList) {
            File file = (File) obj;
            if (file.isFile()) {
                //11.27修改，见jitcommit
                if (index.contains(file.getPath())&&(JitCommit.lastIndex.contains(file.getPath())||file.getPath().contains(JitCommit.tempCommitpath))) {
                    String temp = SHA1.getHash(path + File.separator + file.getName());
                    result = getDigestResult(temp + result, "SHA-1");
                }
            } else if (file.isDirectory() && !file.getName().equals(".jit")) {
                if (index.contains(file.getPath())&&(JitCommit.lastIndex.contains(file.getPath())||file.getPath().contains(JitCommit.tempCommitpath))) {
                    String temp = SHA1.getHash(file.getPath());
                    result = getDigestResult(temp + result, "SHA-1");
                    dfs(path + File.separator + file.getName());
                }
            }
        }
    }


    public static String getDigestResult(String str, String hashAlgorithm) throws NoSuchAlgorithmException {
        MessageDigest mDigest = null;
        mDigest = MessageDigest.getInstance(hashAlgorithm);
        mDigest.update(str.getBytes());
        BigInteger bigInt = new BigInteger(1, mDigest.digest());
        String resultStr = bigInt.toString(16);
        return resultStr;
    }

    @Override
    public String toString() {
        return "040000 tree " + key;
    }

    public static String getValue(File file) throws IOException {
        String filepath = file.getPath();
        StringBuffer sb = new StringBuffer();
        readToBuffer(sb, filepath);
        return sb.toString();
    }

    public static void readToBuffer(StringBuffer buffer, String filePath) throws IOException {
        InputStream is = new FileInputStream(filePath);
        String line; // 每行
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        line = reader.readLine(); 
        while (line != null) {
            buffer.append(line); 
            buffer.append("\n"); 
            line = reader.readLine(); 
        }// 一行一行地读取到buffer中
        reader.close();
        is.close();
    }


}
